/**
 * API测试脚本
 * 用于测试CreateTokenForm表单对应的后端接口
 * 运行方式: npx ts-node src/test/api-test.ts
 */

import axios, { AxiosError } from 'axios';
import { CreateTokenDto, ApiResponse, Token } from '../types/api';

// 配置
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:7172/api';
const TEST_TIMEOUT = 30000; // 30秒超时

// 颜色输出工具
const colors = {
  reset: '\x1b[0m',
  red: '\x1b[31m',
  green: '\x1b[32m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  magenta: '\x1b[35m',
  cyan: '\x1b[36m',
};

function log(color: keyof typeof colors, message: string) {
  console.log(`${colors[color]}${message}${colors.reset}`);
}

// 测试数据集
const testCases = [
  // 基础测试用例
  {
    name: '基础代币创建测试',
    data: {
      name: 'Test Token',
      symbol: 'TEST',
      decimals: 9,
      supply: '1000000',
      description: '这是一个测试代币',
      creator: '3N5UkPsssdMAjjyF5vje7k5pgJoYPsBouPBLbtZaxa2U', // 有效的Solana公钥地址
      enablePrettyAddress: false,
      enableSocialLinks: false,
      revokeUpdateAuthority: false,
      revokeFreezeAuthority: false,
      revokeMintAuthority: false,
    } as CreateTokenDto,
  },
  
  // 启用靓号地址的测试用例
  {
    name: '靓号地址代币创建测试',
    data: {
      name: 'Pretty Address Token',
      symbol: 'PRETTY',
      decimals: 6,
      supply: '500000',
      description: '带有靓号地址的测试代币',
      creator: '3N5UkPsssdMAjjyF5vje7k5pgJoYPsBouPBLbtZaxa2U',
      enablePrettyAddress: true,
      prettyPrefix: 'ABC',
      prettySuffix: '888',
      caseSensitive: false,
      threads: 2,
      enableSocialLinks: false,
      revokeUpdateAuthority: false,
      revokeFreezeAuthority: false,
      revokeMintAuthority: false,
    } as CreateTokenDto,
  },
  
  // 完整功能测试用例
  {
    name: '完整功能代币创建测试',
    data: {
      name: 'Full Feature Token',
      symbol: 'FULL',
      decimals: 8,
      supply: '2000000',
      description: '包含所有功能的完整测试代币',
      image: 'https://example.com/token-logo.png',
      creator: '11111111111111111111111111111112',
      enablePrettyAddress: true,
      prettyPrefix: 'FULL',
      prettySuffix: '999',
      caseSensitive: true,
      threads: 4,
      enableSocialLinks: true,
      website: 'https://example.com',
      twitter: 'https://twitter.com/example',
      telegram: 'https://t.me/example',
      discord: 'https://discord.gg/example',
      revokeUpdateAuthority: true,
      revokeFreezeAuthority: true,
      revokeMintAuthority: false,
    } as CreateTokenDto,
  },
  
  // 边界值测试用例
  {
    name: '边界值测试',
    data: {
      name: 'A'.repeat(32), // 最大长度名称
      symbol: 'ABCDEFGHIJ', // 最大长度符号
      decimals: 0, // 最小小数位
      supply: '999999999999999999', // 大数值
      description: 'B'.repeat(500), // 最大长度描述
      creator: '11111111111111111111111111111112',
      enablePrettyAddress: true,
      prettyPrefix: 'ABCDEFGH', // 最大长度前缀
      prettySuffix: '12345678', // 最大长度后缀
      caseSensitive: true,
      threads: 16, // 最大线程数
      enableSocialLinks: false,
      revokeUpdateAuthority: false,
      revokeFreezeAuthority: false,
      revokeMintAuthority: false,
    } as CreateTokenDto,
  },
  
  // 错误测试用例
  {
    name: '缺少必填字段测试',
    data: {
      // 故意缺少必填字段
      symbol: 'ERROR',
      creator: '11111111111111111111111111111112',
    } as CreateTokenDto,
    expectError: true,
  },
  
  // 无效数据测试用例
  {
    name: '无效数据测试',
    data: {
      name: '', // 空名称
      symbol: '', // 空符号
      decimals: -1, // 无效小数位
      supply: '-100', // 负数供应量
      creator: 'invalid-address', // 无效地址
      enablePrettyAddress: true,
      prettyPrefix: 'TOOLONG123456789', // 过长前缀
      enableSocialLinks: true,
      website: 'not-a-url', // 无效URL
    } as CreateTokenDto,
    expectError: true,
  },
];

// HTTP客户端配置
const httpClient = axios.create({
  baseURL: API_BASE_URL,
  timeout: TEST_TIMEOUT,
  headers: {
    'Content-Type': 'application/json',
  },
});

// 测试统计
let totalTests = 0;
let passedTests = 0;
let failedTests = 0;

// 测试结果记录
interface TestResult {
  name: string;
  passed: boolean;
  error?: string;
  response?: any;
  duration: number;
}

const testResults: TestResult[] = [];

// 健康检查
async function healthCheck(): Promise<boolean> {
  try {
    log('blue', '🔍 执行健康检查...');
    const response = await httpClient.get('/api/health');
    
    if (response.status === 200) {
      log('green', `✅ 后端服务正常运行 (${API_BASE_URL})`);
      return true;
    } else {
      log('red', `❌ 后端服务异常: HTTP ${response.status}`);
      return false;
    }
  } catch (error) {
    log('red', `❌ 无法连接到后端服务: ${error instanceof Error ? error.message : String(error)}`);
    return false;
  }
}

// 靓号地址难度估算测试
async function testPrettyAddressEstimate(): Promise<void> {
  try {
    log('blue', '🔍 测试靓号地址难度估算...');
    
    const params = new URLSearchParams({
      prefix: 'ABC',
      suffix: '888',
      caseSensitive: 'false',
      threads: '2',
    });
    
    const response = await httpClient.get(`/pretty-address/estimate?${params}`);
    
    if (response.status === 200 && response.data.success) {
      log('green', '✅ 靓号地址难度估算接口正常');
      console.log('   难度信息:', response.data.data);
    } else {
      log('red', '❌ 靓号地址难度估算接口异常');
    }
  } catch (error) {
    log('yellow', '⚠️ 靓号地址难度估算接口不可用 (可选功能)');
  }
}

// 图片上传测试
async function testImageUpload(): Promise<void> {
  try {
    log('blue', '🔍 测试图片上传接口...');
    
    // 创建一个测试用的假图片数据
    const formData = new FormData();
    const blob = new Blob(['fake-image-data'], { type: 'image/png' });
    formData.append('image', blob, 'test-image.png');
    
    const response = await httpClient.post('/api/upload', formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    });
    
    if (response.status === 200 && response.data.success) {
      log('green', '✅ 图片上传接口正常');
      console.log('   上传结果:', response.data.data);
    } else {
      log('red', '❌ 图片上传接口异常');
    }
  } catch (error) {
    log('yellow', '⚠️ 图片上传接口不可用 (可选功能)');
  }
}

// 执行单个测试用例
async function runTestCase(testCase: typeof testCases[0]): Promise<TestResult> {
  const startTime = Date.now();
  totalTests++;
  
  try {
    log('cyan', `\n🧪 执行测试: ${testCase.name}`);
    console.log('   测试数据:', JSON.stringify(testCase.data, null, 2));
    
    const response = await httpClient.post<ApiResponse<Token>>('/api/tokens', testCase.data);
    const duration = Date.now() - startTime;
    
    if (testCase.expectError) {
      // 期望出错但成功了
      failedTests++;
      const result: TestResult = {
        name: testCase.name,
        passed: false,
        error: '期望返回错误但接口返回成功',
        response: response.data,
        duration,
      };
      log('red', `❌ 测试失败: ${result.error}`);
      return result;
    }
    
    if (response.status === 200 || response.status === 201) {
      if (response.data.success) {
        passedTests++;
        const result: TestResult = {
          name: testCase.name,
          passed: true,
          response: response.data,
          duration,
        };
        log('green', `✅ 测试通过 (${duration}ms)`);
        console.log('   返回数据:', JSON.stringify(response.data, null, 2));
        return result;
      } else {
        failedTests++;
        const result: TestResult = {
          name: testCase.name,
          passed: false,
          error: response.data.message || '接口返回失败状态',
          response: response.data,
          duration,
        };
        log('red', `❌ 测试失败: ${result.error}`);
        return result;
      }
    } else {
      failedTests++;
      const result: TestResult = {
        name: testCase.name,
        passed: false,
        error: `HTTP状态码异常: ${response.status}`,
        response: response.data,
        duration,
      };
      log('red', `❌ 测试失败: ${result.error}`);
      return result;
    }
  } catch (error) {
    const duration = Date.now() - startTime;
    
    if (testCase.expectError) {
      // 期望出错且确实出错了
      passedTests++;
      const result: TestResult = {
        name: testCase.name,
        passed: true,
        error: `预期错误: ${error instanceof Error ? error.message : String(error)}`,
        duration,
      };
      log('green', `✅ 测试通过 (预期错误): ${result.error} (${duration}ms)`);
      return result;
    }
    
    failedTests++;
    const axiosError = error as AxiosError;
    const errorMessage = axiosError.response?.data || axiosError.message || String(error);
    
    const result: TestResult = {
      name: testCase.name,
      passed: false,
      error: `请求失败: ${JSON.stringify(errorMessage)}`,
      duration,
    };
    log('red', `❌ 测试失败: ${result.error} (${duration}ms)`);
    return result;
  }
}

// 生成测试报告
function generateReport(): void {
  log('blue', '\n📊 测试报告');
  log('blue', '='.repeat(50));
  
  console.log(`总测试数: ${totalTests}`);
  console.log(`通过: ${passedTests} (${((passedTests / totalTests) * 100).toFixed(1)}%)`);
  console.log(`失败: ${failedTests} (${((failedTests / totalTests) * 100).toFixed(1)}%)`);
  
  const avgDuration = testResults.reduce((sum, result) => sum + result.duration, 0) / testResults.length;
  console.log(`平均响应时间: ${avgDuration.toFixed(0)}ms`);
  
  if (failedTests > 0) {
    log('red', '\n❌ 失败的测试:');
    testResults
      .filter(result => !result.passed)
      .forEach(result => {
        console.log(`  - ${result.name}: ${result.error}`);
      });
  }
  
  log('blue', '\n📝 详细结果已保存到 test-results.json');
  
  // 保存详细结果到文件
  const fs = require('fs');
  fs.writeFileSync(
    'test-results.json',
    JSON.stringify({
      summary: {
        total: totalTests,
        passed: passedTests,
        failed: failedTests,
        successRate: ((passedTests / totalTests) * 100).toFixed(1) + '%',
        averageDuration: avgDuration.toFixed(0) + 'ms',
        timestamp: new Date().toISOString(),
      },
      results: testResults,
    }, null, 2)
  );
}

// 主测试函数
async function runTests(): Promise<void> {
  log('magenta', '🚀 开始API接口测试');
  log('magenta', '='.repeat(50));
  
  // 健康检查
  const isHealthy = await healthCheck();
  if (!isHealthy) {
    log('red', '❌ 后端服务不可用，终止测试');
    process.exit(1);
  }
  
  // 测试可选接口
  await testPrettyAddressEstimate();
  await testImageUpload();
  
  // 执行主要测试用例
  log('blue', '\n🧪 开始执行代币创建接口测试...');
  
  for (const testCase of testCases) {
    const result = await runTestCase(testCase);
    testResults.push(result);
    
    // 测试间隔，避免过快请求
    await new Promise(resolve => setTimeout(resolve, 1000));
  }
  
  // 生成报告
  generateReport();
  
  // 退出码
  process.exit(failedTests > 0 ? 1 : 0);
}

// 错误处理
process.on('unhandledRejection', (reason, promise) => {
  log('red', `未处理的Promise拒绝: ${reason}`);
  process.exit(1);
});

process.on('uncaughtException', (error) => {
  log('red', `未捕获的异常: ${error.message}`);
  process.exit(1);
});

// 运行测试
if (require.main === module) {
  runTests();
}

export { runTests, testCases };
